#include "taskFlyport.h"
#include "thingspeak.h"
#include "nimbits.h"
#include "pvoutput.h"
//#include "myaccounts.h"
#include "time.h"
#include "rtcc.h"


// TODO
// 2. calculate energy consumption drop.
// 9. calculate average over timeperiod 
// 4. cleanup simustart, simulactive, resetsimulator
// 5. rtcc is 1 hour behind GMT+1... Dat moet +2 zijn zomeruur en +1 winteruur. Is nu gewoon +2.  
// 5. cleanup t en rh

// TODO : Nimbits - Google Chart tools 
// 5 . Dates are not displayed

// TODO : Configuration 
// 3. get data from config site.

// BUGS


int 	counter;
double 	t = 0;
double 	rh = 0;
float 	simuStartValue=-99.0;
BOOL 	simulActive=TRUE,resetSimulator=TRUE;
extern BOOL    alarmflag;

BOOL 	dailytweetflag=TRUE;
//BOOL 	weeklytweetflag=TRUE; //todo : implement weekly tweet
//BOOL 	monthlytweetflag=TRUE; //todo : implement monthly tweet
//BOOL 	jearlytweetflag=TRUE; //todo : implement jearly tweet

int today;

char	cSendTempTo; // Select the destination for sending the current temp (tweet, nimbits, thingspeaks)	
char 	sTweetOut[150];
float	fWatts;
//char*	cPtr;
static BYTE error = 0;

// start e-mints
INT32 rpk = 0;               // raw pulse KWH counter (private)
INT32 rpk_old = 0;           // value of last read (private)
volatile BOOL CS_WH = FALSE;              // Critical Section for KWH meter (private)
DWORD startTime;
double elapsedTime;
double watts = 0;
char str[250];

t_RTCC mytime, alarmtime;

char curTime[40];



void setRTCCwithNTP(void)
{
	
	DWORD epoch=0;
	DWORD epochtime=0xA2C2A;
	time_t now;
	struct tm *ts;
	
	int GMT_hour_adding = 2; // TODO : get this from the config site website.
	// Or find other solution e.g. set RTCC based on config sites data.
	
	char dateUTC[100];
	char dateUTC1[50];
	char string_serial[50]="waiting...";
	struct TimeFromWeb  {
		// type definition
		char cDayOfWeek[4];
		int  iDay;
		int  iMonth;
		int  iYear;
		int  iHour;
		int  iMinute;
		int  iSecond;
		int  iTZ; // GMT=0, else TimeZone
	} TimeFields;
	
	while(epoch<epochtime)	{
		vTaskDelay(50);
		epoch=SNTPGetUTCSeconds();
	}
	UARTWrite(1, "SNTP done!\r\n");
	vTaskDelay(20);
	epoch=SNTPGetUTCSeconds();
	now=(time_t)epoch;
	ts = localtime(&now);
	// GMT adding 2 hours test
	ts->tm_hour = (ts->tm_hour + GMT_hour_adding)%24;
	// Correct if overflowed hour 0-24 format
	/*if(ts->tm_hour > 24){
		ts->tm_hour = ts->tm_hour - 24;
	}
	else if(ts->tm_hour < 0){ts->tm_hour = ts->tm_hour +24;}*/
	
	strftime(dateUTC1, sizeof(dateUTC1), "%Y-%m-%d / %H:%M.%S", ts);
	sprintf(string_serial, "%s", dateUTC1);
	UARTWrite(1,string_serial);
	
	//TimeFields.cDayOfWeek="";
	TimeFields.iDay=ts->tm_mday;
	TimeFields.iMonth=ts->tm_mon+1;
	TimeFields.iYear=ts->tm_year;
	TimeFields.iHour=ts->tm_hour;
	TimeFields.iMinute=ts->tm_min;
	TimeFields.iSecond=ts->tm_sec;
	
	sprintf(dateUTC,"Set RTCC to : %s\r\n",dateUTC1);
	UARTWrite(1,dateUTC);
	UARTFlush(1);
	
	mytime.year = (BYTE)TimeFields.iYear%100;
	mytime.month =  (BYTE)TimeFields.iMonth;
	today = mytime.day =  (BYTE)TimeFields.iDay;
	mytime.hour =  (BYTE)TimeFields.iHour;
	mytime.min =  (BYTE)TimeFields.iMinute;
	mytime.sec =  (BYTE)TimeFields.iSecond;
	mytime.dweek = (BYTE)1;
	RTCCWrite (&mytime);
}

double getElapsedTime()
{
	//char timeStr[250];
	
	DWORD endTime = TickGetDiv256();
	DWORD ElapsedTimeMs = (endTime - startTime ) * 4 ;
	startTime = endTime;
	
	double ElapsedTime= ((double)ElapsedTimeMs/(double)1000.0);
    
	//old code resulted in negative times --> to be deleted
    //double ElapsedTime= ((double)ElapsedTimeMs/(double)10.0) + (double)0.5;
    //ElapsedTime = ElapsedTime/(double)100;
	//--> to be deleted
	//sprintf(timeStr,"timediff : %0.2f\n",(double)ElapsedTime);
	//UARTWrite(1,timeStr );
	
	return ElapsedTime;
}

void printTime(void)
{
	RTCCRead(&mytime);
	sprintf(curTime,"Year : %02d, Month : %02d, Day : %02d, Time : %02d:%02d:%02d\n",mytime.year, mytime.month, mytime.day, mytime.hour, mytime.min, mytime.sec);
	UARTWrite(1,curTime);
}

// The interrupt routine
void KWh_irq()
{
  rpk++;  // just increment raw pulse counter.
  elapsedTime =   getElapsedTime();
  watts = (double)1800.0/(double)elapsedTime;
  //UARTWrite(1,"pulse received: \n");
  //sprintf(str,"avarage Watts : %0.2f\n",(double)watts);
  //UARTWrite(1,str);
  //sprintf(str,"Pulses : %i\n",(int)rpk);
  //UARTWrite(1,str);
  //sprintf(str,"elapsed time : %0.2f\n",(double)elapsedTime);
  //UARTWrite(1,str);
  UARTWrite(1,".");
  
  if (rpk > 1000000000)     // reset pulse counter after 10e9 pulse = 500.000 KW 
  {
    if (FALSE == CS_WH)    // in critical section?  // assumption IRQ-call is handled atomic on arduino.
    {
      rpk -= rpk_old;
      rpk_old = 0;
    }
  }
  rh = watts;
  t = rpk*0.5; // Dit zijn de Wh's 
}

void skipFirstPulse()
{
	elapsedTime =   getElapsedTime();
	INTInit (2, KWh_irq , 1);
}

BYTE tweet(char* message)
{
	BYTE error=thingTWEET("L4OSX1HO3HNU4PE9", message);
	if(error){
		UARTWrite(1, "\n tweet ERROR \n ");
	}
	else {
		UARTWrite(1, "Following tweet was sent :\n");
		UARTWrite(1, message);
		UARTWrite(1, "\n");
	}
	return error;
}

BYTE sentToThingSpeak()
{
	BYTE error=wfTHINGSPEAK("D3908GUXP6364589", &fWatts, (int)1);
	if(error){
		UARTWrite(1, "\n thingspeak returned an ERROR \n ");
	}
	else {
		UARTWrite(1, "Thingspeak value was succesfully sent\n");
	}
	return error;
}

BYTE sentToNimbits()
{
	wfNIMBITS("app.nimbits.com", "harold.vanderveken@gmail.com", "c7ffd9c2-8f60-4c08-8f1b-462b75a66066", "1234", &fWatts);
	error = 0; // wfNIMBITS does not return an error.
	if(error){
		UARTWrite(1, "\n nimbits returned an ERROR \n ");
	}
	else {
		UARTWrite(1, "Nimbits value was succesfully sent\n");
	}
	return error;
}

BYTE sentToPVOutput()
{
	char apiKey[50] = "23af87bbaeb43a7ca3953ca47ccd884ff627c9ac";
	char systemId[10] = "11818";
	char data[100];
	
	RTCCRead(&mytime);
	sprintf(data,"data=20%02d%02d%02d,%02d:%02d,%1.0f,%1.0f",mytime.year, mytime.month, mytime.day, mytime.hour, mytime.min, t, (double)fWatts);
	BYTE error=wPVOutput(systemId, apiKey, data);
	if(error){
		UARTWrite(1, "\n PVoutput returned an ERROR \n ");
	}
	else {
		UARTWrite(1, "PVoutput value was succesfully sent\n");
	}
	return error;
}

BOOL isNewDay()
{
	RTCCRead(&mytime);
	if (mytime.day == today) {return FALSE;} //still today
	else // next day
	{
		today = mytime.day;
		return TRUE;
	}
}



char* getDailyTweetMSg(void)
{
	sprintf(sTweetOut,"e-mints daily tweet of %s : energy used=%0.2f\n",curTime, t);
	return sTweetOut;
}

// end e-mints

void FlyportTask()
{
   WFConnect(WF_DEFAULT);
   
   while (WFStatus != CONNECTED);
   
   // Get and set RTCC with NTP
   setRTCCwithNTP();
   
   //Configure the alarms on the RTCC.
   // Daily alarm
   alarmtime.hour = 0;
   alarmtime.min = 0;
   RTCCSetAlarm( &alarmtime,REPEAT_INFINITE,EVERY_TEN_MIN);
   //RTCCSetAlarm( &alarmtime,REPEAT_INFINITE,EVERY_DAY);
   
   // TODO weekly and monthly alarm
   RTCCRunAlarm(1);
   
   // get the starttime needed to calculte the power
   startTime = TickGetDiv256(); // First strattime will not be used.
   
   // initialise interrupt on I/O In3
   IOInit(p9, indown); 
   IOInit ( p9, EXT_INT2 );
   INTInit (2, skipFirstPulse , 1);
   INTEnable(2);
         
   // ............... START of infinite WHILE LOOP
   while(1)
   {         
	  // Switch on D4Out to indicate we are in while loop
	  IOPut (D4Out, ON);
	  vTaskDelay(100);
	  
	  while (WFStatus != CONNECTED){
		  printTime();
		  sprintf(curTime,"\tWIFI STATUS : %i\n", WFStatus);
		  UARTWrite(1,curTime);
		  vTaskDelay(1000);
		  if (WFStatus == 0) WFConnect(WF_DEFAULT);
			  
	  }
	  
	  
	  
	  
	  /*
	  if (WFStatus != CONNECTED){
		  printTime();
		  sprintf(curTime,"\tWIFI STATUS : %i\n", WFStatus);
		  UARTWrite(1,curTime);
		  WFConnect(WF_DEFAULT);
		  counter = 0;
		  while (WFStatus != CONNECTED){
			  vTaskDelay(100);
			  printTime();
			  sprintf(curTime,"Waiting for connect...\n\tWIFI STATUS : %i\n\tretry : %i\n",WFStatus, counter++);
			  UARTWrite(1,curTime);
		  }
	  }
	  */
	  
	  //sent data every minute
	  if(alarmflag == TRUE){
		  alarmflag = FALSE;
		  if (isNewDay()) {
			  UARTWrite(1,"New day started ... resetting rpk");
			  rpk = 0;
		  } // reset the pulse count every new day.
		  
		  fWatts=watts;

	  
		  // show time on serial UART
		  printTime();
		  
		  // Daily tweet
		  /*if(dailytweetflag == TRUE)
		  { // sent daily tweet
			  if(!tweet(getDailyTweetMSg()))
			  { // tweet was ok ... anders retry
				  dailytweetflag = FALSE;
			  };
		  }
		  else 
		  { // check if new day started 
			if(mytime.day == today){ // still today -> do nothing
			}
			else { // Its a new day
				dailytweetflag = TRUE;
				today = mytime.day;
			}
		  }*/
		  
		  //NIMBITS
/*		  counter = 0;
		  do {
			  vTaskDelay(10);
			  error = sentToNimbits();
			  counter++;
		  } while (error && counter < 10);*/
		  
		  //THINGSPEAK
/*		  counter = 0;
		  do {
			  vTaskDelay(10);
			  error = sentToThingSpeak();
			  counter++;
		  } while (error && counter < 10);*/
		  
		  //pvoutput
		  counter = 0;
		  do {
			  vTaskDelay(10);
			  error = sentToPVOutput();
			  counter++;
		  } while (error && counter < 10);
		  
	  }
	  
	  
	  
   }
}
